<?php

namespace App\Admin\Controllers;

use App\Admin\Repositories\Order;
use App\Exceptions\InternalException;
use App\Exceptions\InvalidRequestException;
use App\Http\Requests\Admin\HandleRefundRequest;
use Dcat\Admin\Form;
use Dcat\Admin\Grid;
use Dcat\Admin\Layout\Content;
use App\Models\Order as OrderModel;
use Dcat\Admin\Controllers\AdminController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\Request;

// 后台订单管理控制器
class OrderController extends AdminController
{
    use ValidatesRequests;

    /**
     * Make a grid builder.
     *
     * @return Grid
     */
    protected function grid()
    {
        return Grid::make(
            new Order(['user']),
            function (Grid $grid) {
                $grid->model()->orderBy('id', 'desc');
                $grid->id->sortable();
                $grid->no->filter(Grid\Column\Filter\Like::make());
                $grid->column('user.name', '用户名')->hide();
                $grid->total_amount->filter(Grid\Column\Filter\Between::make());
                $grid->paid_at->filter(Grid\Column\Filter\Between::make()->datetime());
                $grid->payment_method->filter(Grid\Column\Filter\In::make(['alipay' => '支付宝支付', 'wechatPay' => '微信支付']));
                $grid->payment_no->filter(
                    Grid\Column\Filter\Like::make()
                )->hide();
                $grid->refund_status->display(
                    function ($value) {
                        return OrderModel::$refundStatusMap[$value];
                    }
                )->filter(
                    Grid\Column\Filter\In::make(OrderModel::$refundStatusMap)
                );
                $grid->ship_status->display(
                    function ($value) {
                        return OrderModel::$shipStatusMap[$value];
                    }
                )->filter(
                    Grid\Column\Filter\In::make(OrderModel::$shipStatusMap)
                );
                $grid->closed->filter(
                    Grid\Column\Filter\In::make(
                        [
                            0 => '否',
                            1 => '是',
                        ]
                    )
                )->display(
                    function ($value) {
                        return $value ? '是' : '否';
                    }
                );
                $grid->created_at->filter(Grid\Column\Filter\Between::make()->datetime())->hide();

                $grid->disableCreateButton(); // 禁止创建
                $grid->actions(
                    function ($actions) {
                        // 禁止删除和编辑
                        $actions->disableDelete();
                        $actions->disableEdit();
                    }
                );

                $grid->tools(
                    function ($tools) {
                        $tools->batch(
                            function ($batch) {
                                $batch->disableDelete();
                            }
                        );
                    }
                );

                $grid->filter(
                    function (Grid\Filter $filter) {
                        $filter->equal('id');

                    }
                );
            }
        );
    }

    // 自定义详情页面
    public function show($id, Content $content)
    {
        return $content->header('订单')
            ->description('详情')
            ->body(view('admin.orders.show', ['order' => OrderModel::query()->find($id)]));
    }

    // 订单发货功能
    public function ship(OrderModel $order, Request $request)
    {
        // 判断订单是否支付
        if (!$order->paid_at) {
            throw new InvalidRequestException('该订单未付款');
        }

        // 判断订单发货状态是否为未发货
        if ($order->ship_status !== OrderModel::SHIP_STATUS_PENDING) {
            throw new InvalidRequestException('该订单已发货');
        }

        $data = $this->validate(
            $request,
            [
                'express_company' => ['required'],
                'express_no' => ['required'],
            ],
            [
                'required' => '不能为空'
            ],
            [
                'express_company' => '物流公司',
                'express_no' => '物流单号',
            ]
        );

        // 将订单发货状态改为已发货, 并保存物流休息
        $order->update(
            [
                'ship_status' => OrderModel::SHIP_STATUS_DELIVERED,
                'ship_data' => $data,
            ]
        );

        return redirect()->back();
    }
    
    // 处理用户退款
    public function handleRefund(OrderModel $order, HandleRefundRequest $request)
    {
        // 判断订单状态是否正确
        if ($order->refund_status !== OrderModel::REFUND_STATUS_APPLIED) {
            admin_error('异常', '订单状态异常');
        }
        // 是否同意退款
        if ($request->input('agree')) {
            // 同意退款
            $extra = $order->extra ?: [];
            unset($extra['refund_disagree_reason']); // 去除不同意退款的理由
            $order->update([
                'extra' => $extra
            ]);
            // 调用退款逻辑
            $this->_refundOrder($order);
        } else {
            // 不同意退款 (不同意退款必须理由)
            $extra = $order->extra ?: [];
            $extra['refund_disagree_reason'] = $request->input('reason');

            // 将订单的退款状态改为未退款
            $order->update([
               'refund_status' => OrderModel::REFUND_STATUS_PENDING,
               'extra' => $extra
            ]);
        }
        return $order;
    }
    
    // 处理退款逻辑
    private function _refundOrder(OrderModel $order)
    {
        switch ($order->payment_method) {
            case 'alipay':
                // 生成退款单号
                $refundNo = OrderModel::getAvailableRefundNo();
                // 调用支付宝的退款
                $ret = app('alipay')->refund([
                    'out_trade_no' => $order->no,
                    'refund_amount' => $order->total_amount,
                    'out_request_no' => $refundNo
                ]);

                // 根据支付宝的文档, 有sub_code说明退款失败
                if ($ret->sub_code) {
                    // 将退款失败的保存存入extra字段
                    $extra = $order->extra;
                    $extra['refund_faild_code'] = $ret->sub_code;

                    // 把退款变为失败
                    $order->update([
                       'refund_no' => $refundNo,
                       'refund_status' => OrderModel::REFUND_STATUS_FAILED,
                       'extra' => $extra
                    ]);
                } else {
                    // 退款成功
                    $order->update([
                        'refund_no' => $refundNo,
                        'refund_status' => OrderModel::REFUND_STATUS_SUCCESS
                    ]);
                }
                break;
            case 'wechat':
                break;
            default:
                throw new InternalException('未知支付方法:'. $order->payment_method);
                break;
        }
    }
    
    /**
     * Make a form builder.
     *
     * @return Form
     */
    protected function form()
    {
        return Form::make(
            new Order(),
            function (Form $form) {
                $form->display('id');
                $form->text('no');
                $form->text('user_id');
                $form->text('address');
                $form->text('total_amount');
                $form->text('remark');
                $form->text('paid_at');
                $form->text('payment_method');
                $form->text('payment_no');
                $form->text('refund_status');
                $form->text('refund_no');
                $form->text('closed');
                $form->text('reviewed');
                $form->text('ship_status');
                $form->text('ship_data');
                $form->text('extra');

                $form->display('created_at');
                $form->display('updated_at');
            }
        );
    }
}
